home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EuroCD 3
/
EuroCD 3.iso
/
Programming
/
vbcc
/
pasm
/
ppcasm.h
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-24
|
21KB
|
590 lines
/* $VER: pasm ppcasm.h V0.7 (14.12.97)
*
* This file is part of pasm, a portable PowerPC assembler.
* Copyright (c) 1997 Frank Wille
*
* pasm is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-97 by Volker Barthelmann.
* pasm may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v0.7 (14.12.97) phx
* Define "NetBSDAmiga68k" changed to "NetBSD68k".
* v0.6 (30.10.97) phx
* More options. GlobalVars: optinstrmode and supermode.
* v0.5 (12.10.97) phx
* Add userdeflist and usrdefs to GlobalVars for symbol definitions
* via the command line.
* .set allows symbols to be reused.
* Last line of a source text was ignored, if newline is missing.
* v0.4 (05.07.97) phx
* Program returns EXIT_FAILURE if an error occurs.
* Base address for absolute code may be set with -B option.
* EHF support.
* Added R_PPC_TOC16 relocation type.
* Option -x automatically declares unknown symbols as
* externally defined. New GlobalVars entry: autoextern.
* Runs on Linux/DEC-Alpha with 64-bit integers.
* Changed program name from "PPCasm" to "pasm". Reason: There
* is already a PPCasm for Apple Macintosh.
* v0.3 (20.04.97) phx
* Using correct names for PowerPC relocations.
* Added little-endian conversion macros.
* v0.2 (25.03.97) phx
* Writes ELF object for 32-bit PowerPC big-endian. Either absolute
* or ELF output format may be selected. ELF is default for all
* currently supported platforms. PPCasm supports nine different
* relocation types (there are much more...).
* Compiles and works also under NetBSD/amiga (68k).
* Changed function declaration to 'new style' in all sources
* (to avoid problems with '...' for example).
* Included NetBSD/amiga as supported architecture.
* v0.1 (11.03.97) phx
* First test version with all PowerPC instructions and most
* important directives. Only raw, absolute output.
* v0.0 (14.02.97) phx
* File created. Project started.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
/* program's name */
#define PNAME "pasm"
/* version/revision */
#define VERSION 0
#define REVISION 65
/* architecture specific defines */
#if defined (AmigaOS68k)
#define MACHINE "Amiga OS/M68k"
#define BIGENDIAN
#define STDTYPES
#elif defined (AmigaOSPPC)
#define MACHINE "Amiga OS/PowerPC"
#define BIGENDIAN
#define STDTYPES
#elif defined (NetBSD68k)
#define MACHINE "NetBSD/M68k"
#define BIGENDIAN
#define STDTYPES
#elif defined (SolarisSparc)
#define MACHINE "Solaris/Sparc"
#define BIGENDIAN
#define STDTYPES
#elif defined (SunOSSparc)
#define MACHINE "SunOS/Sparc"
#define BIGENDIAN
#define STDTYPES
#elif defined (SCOi386)
#define MACHINE "SCO/i386"
#define LITTLEENDIAN
#define STDTYPES
#elif defined (Linuxi386)
#define MACHINE "Linux/i386"
#define LITTLEENDIAN
#define STDTYPES
#elif defined (LinuxAlpha)
#define MACHINE "Linux/Alpha"
#define LITTLEENDIAN
#define TYPES64BIT
#else
#error Unsupported architecture! Please adapt the source text.
#endif
#ifdef STDTYPES
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int int16;
typedef unsigned short int uint16;
typedef signed long int int32;
typedef unsigned long int uint32;
typedef signed char bool;
#elif defined (TYPES64BIT)
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed int int32;
typedef unsigned int uint32;
typedef int bool;
#else
#error Unsupported architecture! Please adapt the source text.
#endif
/* endian conversion */
#if defined (BIGENDIAN)
#define ECH(x) x
#define ECW(x) x
#define ECVH(x) x
#define ECVW(x) x
#elif defined (LITTLEENDIAN)
#define ECH(x) (((x)&0xff)<<8|((x)&0xff00)>>8)
#define ECW(x) (((x)&0xff)<<24|((x)&0xff00)<<8|((x)&0xff0000)>>8|((x)&0xff000000)>>24)
#define ECVH(x) l2bh(x)
#define ECVW(x) l2bw(x)
#else
#error You have to define either BIGENDIAN or LITTLEENDIAN.
#endif
/* program constants */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#define FNAMEBUFSIZE 1024 /* buffer size for file names */
#define EXPSTACKSIZE 32 /* maximum arguments in an expression */
/* structures */
struct node {
struct node *next;
struct node *pred;
};
struct list {
struct node *first;
struct node *dummy;
struct node *last;
};
struct CPUInstr {
struct CPUInstr *hash_chain; /* next instruction in hash chain */
char *name; /* instruction's name */
uint16 flags; /* format flags */
uint8 type; /* instruction format, see defines */
uint8 opcd; /* opcode (bit 0-5) */
uint8 fieldD; /* preset D field (bit 6-10) */
uint8 fieldA; /* preset D field (bit 11-15) */
uint16 xo; /* extended opcode (bit 21-31) */
};
/* CPU instruction formats */
#define T_I 0 /* Bx */
#define T_B 1 /* BCx */
#define T_DD 2 /* LWZ */
#define T_DI 3 /* ADDI */
#define T_DS 4 /* LD */
#define T_X 5 /* AND */
#define T_IMM 6 /* MTFSFI */
#define T_XLB 7 /* BCLRx */
#define T_XSPR 8 /* MFSPR */
#define T_XCRM 9 /* MTCRF */
#define T_XFL 10 /* MTFSF */
#define T_XS 11 /* SRADIx */
#define T_A 12 /* FMADDx */
#define T_M 13 /* RLWIMIx */
#define T_MD 14 /* RLDICx */
#define T_CMP 15 /* CMP */
/* CPU instruction flags */
#define F_SUPP_D 0x01 /* D = 0 */
#define F_SUPP_A 0x02 /* A = 0 */
#define F_SUPP_B 0x04 /* B = 0 */
#define F_SUPP_C 0x08 /* C = 0 */
#define F_CRF_D 0x10 /* D = CR field */
#define F_CRF_S 0x20 /* S = CR field */
#define F_SWAP 0x40 /* S instr.: D = S, A and S are swapped */
#define F_SIGNED 0x80 /* 16 bit signed immediate */
#define F_64BIT 0x100 /* 64 bit instruction */
#define F_SUPER 0x200 /* supervisor-only instruction */
#define F_OPTIONAL 0x400 /* optional instruction */
#define F_EXTENDED 0x8000 /* extended mnemonic */
struct Directive {
struct Directive *hash_chain; /* next directive in hash chain */
char *name; /* directive's name */
void (*dfunct)();
};
struct Macro {
struct Macro *hash_chain; /* next macro in hash chain */
char *name; /* macro's name */
char *text; /* ptr to first macro line */
unsigned long nlines; /* number of lines in this macro */
};
struct Section {
struct node n;
char *name; /* section's name */
uint8 type; /* type: code, data, bss, offsets, ... */
uint8 flags;
uint8 protection; /* readable, writable, executable, ... */
uint8 alignment; /* number of bits, which have to be zero */
unsigned long pc; /* current program counter (sect. offset) */
unsigned long size; /* size of section in bytes */
void *contents; /* contents, allocated in pass 2 */
void *data;
struct list reloclist; /* section offsets to relocate */
struct list xreflist; /* external references in this section */
uint32 index; /* e.g. section header index for ELF */
};
/* section types */
#define ST_UNDEFINED 0
#define ST_CODE 1 /* section contains code */
#define ST_DATA 2 /* section contains initialized data */
#define ST_UDATA 3 /* section contains uninitialized data */
#define ST_STRUCT 4 /* offset section (will be discarded) */
/* section flags */
#define SF_DISCARD 1 /* can be discarded (e.g. ST_STRUCT) */
#define SF_UNINITIALIZED 2 /* section has uninitialized contents */
/* protection */
#define SP_READ 1
#define SP_WRITE 2
#define SP_EXEC 4
#define SP_SHARE 8
struct Symbol {
struct Symbol *hash_chain; /* next symbol in hash chain */
char *name; /* symbol's name */
uint32 value; /* absolute value or relocation offset */
struct Section *relsect; /* symbol def. relative to this section */
uint8 type; /* absolute, relocatable or extern */
uint8 flags;
uint8 info; /* section, function or object */
uint8 bind; /* local or global */
uint32 size; /* object's size in bytes */
};
/* symbol type */
#define SYM_UNDEF 0
#define SYM_ABS 1
#define SYM_RELOC 2
#define SYM_EXTERN 3
/* object type */
#define SYMI_NOTYPE 0
#define SYMI_OBJECT 1
#define SYMI_FUNC 2
#define SYMI_SECTION 3
#define SYMI_FILE 4
/* symbol bind */
#define SYMB_NONE 0
#define SYMB_LOCAL 1
#define SYMB_GLOBAL 2
#define SYMB_WEAK 3
struct Reloc {
struct node n;
unsigned long offset; /* section-offset of relocation */
uint32 addend; /* add this to relocation value */
struct Section *relocsect; /* base addr of this sect. has to be added */
uint8 type;
};
/* reloc types (identical with the reloc types used for ELF) */
#define R_NONE 0
#define R_PPC_ADDR32 1 /* 32-bit relocation */
#define R_PPC_ADDR24 2 /* 26-bit relocation for B-instruction */
#define R_PPC_ADDR16 3 /* 16-bit relocation */
#define R_PPC_ADDR16_LO 4 /* relocation of the lower half-word */
#define R_PPC_ADDR16_HI 5 /* relocation of the higher half-word */
#define R_PPC_ADDR16_HA 6 /* higher half-word reloc. for ADDI */
#define R_PPC_ADDR14 7 /* BC-instruction, 16-bit absolute */
#define R_PPC_ADDR14_BRTAKEN 8
#define R_PPC_ADDR14_BRNTAKEN 9
#define R_PPC_REL24 10 /* relative 26-bit (PowerPC B-instruction) */
#define R_PPC_REL14 11 /* BC-instruction, 16-bit relative */
#define R_PPC_REL14_BRTAKEN 12
#define R_PPC_REL14_BRNTAKEN 13
#define R_PPC_GOT16 14
#define R_PPC_GOT16_LO 15
#define R_PPC_GOT16_HI 16
#define R_PPC_GOT16_HA 17
#define R_PPC_PLTREL24 18
#define R_PPC_COPY 19
#define R_PPC_GLOB_DAT 20
#define R_PPC_JMP_SLOT 21
#define R_PPC_RELATIVE 22
#define R_PPC_LOCAL24PC 23
#define R_PPC_UADDR32 24
#define R_PPC_UADDR16 25
#define R_PPC_REL32 26 /* section base offset */
#define R_PPC_PLT32 27
#define R_PPC_PLTREL32 28
#define R_PPC_PLT16_LO 29
#define R_PPC_PLT16_HI 30
#define R_PPC_PLT16_HA 31
#define R_PPC_SDAREL16 32
#define R_PPC_SECTOFF 33
#define R_PPC_SECTOFF_LO 34
#define R_PPC_SECTOFF_HI 35
#define R_PPC_SECTOFF_HA 36
#define R_PPC_TOC16 255
struct XReference {
struct node n;
struct Symbol *xsymbol; /* external symbol, which is referenced */
unsigned long offset;
uint32 addend;
uint8 type; /* relocation type, see struct Reloc */
uint8 size; /* size of reference in bytes (3 = 26bit) */
};
struct ParsedLine {
uint8 type; /* opcode type */
uint8 flags;
int8 branch_hint; /* 0=no hint, 1=b. taken(+), -1=not taken(-)*/
uint8 narg; /* value for $NARG, when calling macro */
char *lineptr; /* ptr to source text line */
void *opcode; /* ptr to CPUInstr, Directive or SourceText */
char *operand; /* ptr to operand-string */
};
/* opcode types */
#define OT_IGNORE 0 /* line is empty or commented out */
#define OT_INSTRUCTION 1
#define OT_DIRECTIVE 2
#define OT_MACRO 3
#define OT_SECTION 4
/* flags */
#define PLF_NONEWLINE 1 /* new statement is still part of same line */
#define PLF_ALIGN 2
struct SourceText { /* start address and size of all text files */
struct node n;
char *name; /* name of source, include file or macro */
char *text; /* source text pointer */
unsigned long nlines; /* number of lines in source text */
struct ParsedLine *plin; /* ParsedLine structures for nlines */
};
#define MAX_MACPARAMS 10 /* macro parameters \0-\9 */
struct MacroParams {
char *param[MAX_MACPARAMS]; /* parameter strings, which replace \x */
uint32 call_id; /* macro call id */
uint32 narg; /* number of arguments */
char param0[2]; /* parameter 0 contains the branch hint */
};
struct SourceThread { /* main source, includes and macros */
struct SourceThread *prev; /* previous source thread */
struct MacroParams *macro; /* only assigned in macro mode */
struct SourceText *csource; /* ptr to current source text node */
char *lineptr; /* source text pointer to current line */
char *srcptr; /* current source text pointer */
unsigned long line; /* current line inside this thread */
struct Macro *macskip; /* indicates macro skip mode */
};
struct Expression {
uint32 value;
uint8 type; /* same type definitions as used for Symbol */
uint8 reloctype; /* see struct Reloc */
struct Symbol *symbol; /* reloc or extern symbol, used in exp. */
};
struct UserDefine {
struct node n;
char *line; /* .set <symbol>,<assignment> */
};
#define DEF_MAXERRORS 5
#define MAX_INCPATHS 8
#define MAX_IFLEVELS 16
#define LINEBUFSIZE 1024
#define STRBUFSIZE 256
/* number of entries in hash tables */
#define SYMHTABSIZE 0x4000 /* symbol hash table */
#define INSTRHTABSIZE 0x1000 /* instruction hash table */
#define DIRHTABSIZE 0x800 /* directive hash table */
#define MACROHTABSIZE 0x800 /* macro hash table */
/* supported output formats */
#define OFMT_ABSOLUTE 0
#define OFMT_ELF 1
#define OFMT_EHF 2
#define OFMT_LAST 2
struct GlobalVars {
char *source_name; /* source text file name */
char *dest_name; /* output file name */
/* options */
bool dontwarn; /* suppress warnings */
bool noregsymbols; /* don't predefine register symbols etc. */
bool noextmnemo; /* no extended mnemonics */
bool sixtyfourmode; /* 64-bit mode activated */
bool optinstrmode; /* optional instructions */
bool supermode; /* supervisor mode instructions */
bool autoextern; /* autom. declare undef. sym. as extern */
uint8 output; /* output format */
struct list userdeflist; /* user defines */
bool usrdefs;
int maxerrors; /* # of errors to display, before aborting */
int errcnt; /* number of errors displayed */
int returncode; /* return code for exit() */
char *incpaths[MAX_INCPATHS]; /* paths where to search for files */
char *ident; /* unit identification or comment */
char *file; /* source file name for debugging */
unsigned long absbase; /* base address for absolute code */
struct list sourcelist; /* source text list */
struct list sectionlist; /* defined sections */
struct SourceThread *cthread; /* current source thread */
struct Section *csect; /* current section */
struct Symbol *lcsym; /* location counter symbol '$' */
struct Symbol *nargsym; /* symbol for number of arguments '$NARG' */
uint32 macrocnt; /* incremented on every macro invocation */
unsigned long absline; /* absolute line number */
uint8 pass; /* 0 or 1 */
uint8 iflevel; /* current level for conditional assembly */
uint8 ifignore; /* number of else/endifs to ignore */
bool ifcond[MAX_IFLEVELS]; /* ifcond[0] is always TRUE */
bool signedexp; /* current expression to eval is signed */
bool alignflag,vc;
/* TOC */
int rtoc; /* register number for toc-mode */
struct Section *tocsect; /* ptr to TOC section, or NULL */
/* hash tables */
struct Symbol **symbols; /* symbol hash table */
struct CPUInstr **instr; /* instruction hash table */
struct Directive **directives; /* directive hash table */
struct Macro **macros; /* macro hash table */
/* buffers */
char linebuf[LINEBUFSIZE]; /* buffer for a whole source text line */
char strbuf[STRBUFSIZE]; /* string buffer for labels, opcodes, etc. */
uint8 alignment_bytes[4]; /* four zero bytes */
};
/* global functions */
/* main.c */
#ifndef MAIN_C
extern struct GlobalVars gvars;
extern void cleanup(struct GlobalVars *);
#endif
/* version.c */
#ifndef VERSION_C
extern void show_version(void);
extern void show_usage(void);
#endif
/* pass.c */
#ifndef PASS_C
extern void exec_pass1(struct GlobalVars *);
extern void pass1(struct GlobalVars *,struct SourceText *,
struct MacroParams *,struct SourceThread *);
extern struct SourceText *include_source(struct GlobalVars *,char *);
extern void exec_pass2(struct GlobalVars *);
extern void pass2(struct GlobalVars *,struct SourceText *,
struct MacroParams *,struct SourceThread *);
extern struct SourceText *get_source(struct GlobalVars *);
#endif
/* support.c */
#ifndef SUPPORT_C
extern void *alloc(size_t);
extern void *alloczero(size_t);
extern char *allocstring(char *);
extern void initlist(struct list *);
extern void addtail(struct list *,struct node *);
extern struct node *remhead(struct list *);
extern struct node *remnode(struct node *);
extern char *mapfile(struct GlobalVars *,char *);
extern void checkrange(uint32,int,bool);
extern void lower_case(char *);
#ifdef LITTLEENDIAN
extern uint16 l2bh(uint16);
extern uint32 l2bw(uint32);
#endif
#endif
/* eval.c */
#ifndef EVAL_C
extern char *getsymbol(struct GlobalVars *,char *);
extern char *getarg(struct GlobalVars *,char *);
extern char *skipspaces(char *);
extern char *remquotes(char *);
extern void checkEOL(char *);
extern char *skipexpression(struct GlobalVars *,char *);
extern void read_macro_params(struct GlobalVars *,struct ParsedLine *,
struct MacroParams *,char *);
extern char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
extern uint32 makereloc(struct GlobalVars *,struct Expression *);
extern uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
extern char *getintexp(struct GlobalVars *,char *,uint32 *);
extern char *eval_expression(struct GlobalVars *,struct Expression *,char *);
#endif
/* tables.c */
#ifndef TABLES_C
extern void init_hashtables(struct GlobalVars *);
extern void add_macro(struct GlobalVars *,struct Macro *);
extern struct Symbol *add_symbol(struct GlobalVars *,char *,uint8,uint32);
extern unsigned long elf_hash(unsigned char *);
extern struct Symbol *search_symbol(struct GlobalVars *,char *);
extern struct Section *search_section(struct GlobalVars *,char *);
extern void search_opcode(struct GlobalVars *,struct ParsedLine *,
char *,char *);
#endif
/* errors.c */
#ifndef ERRORS_C
extern void error(int,...);
extern void ierror(char *,...);
#endif
/* predefs.c */
extern char stdsects[];
extern char stdsets[];
extern char *xmnemos[];
/* elfrelocnames.c */
extern char *elfrel_name[];
#define ELFRELNAMMSK 0x3f /* number of names in elfrel_name[] minus 1 */
/* instructions.c */
#ifndef INSTRUCTIONS_C
extern struct CPUInstr instructions[];
extern void instr(struct GlobalVars *,struct ParsedLine *);
extern char *check_comma(char *);
extern void pcadd(struct GlobalVars *,unsigned long);
extern void store_byte(struct GlobalVars *,uint8);
extern void store_half(struct GlobalVars *,uint16);
extern void store_word(struct GlobalVars *,uint32);
extern void store_float(struct GlobalVars *,double);
extern void store_double(struct GlobalVars *,double);
extern void store_space(struct GlobalVars *,unsigned long);
#endif
/* directives.c */
#ifndef DIRECTIVES_C
extern struct Directive directives[];
extern void activate_section(struct GlobalVars *,struct Section *);
extern void alignment(struct GlobalVars *,unsigned long);
extern char escchar(char);
#endif
/* output_abs.c */
#ifndef OUTPUT_ABS_C
extern void output_absolute(struct GlobalVars *);
#endif
/* output_elf.c */
#ifndef OUTPUT_ELF_C
extern void output_elf32msb(struct GlobalVars *);
#endif
/* output_ehf.c */
#ifndef OUTPUT_EHF_C
extern void output_ehf(struct GlobalVars *);
#endif